﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Newtonsoft.Json;
using NPMonitor.DataModel;
using NPMonitor.Implementation;
using NPMonitor.Implementation.Store;
using NPMonitor.Web.Code;

namespace NPMonitor.Web.Handler
{
    /// <summary>
    /// Summary description for AjaxService
    /// </summary>
    public class JobsHandler : IHttpHandler
    {
        #region Private Members

        private string Operation { get; set; }

        protected HttpRequest Request
        {
            get
            {
                return HttpContext.Current.Request;
            }
        }

        protected HttpResponse Response
        {
            get
            {
                return HttpContext.Current.Response;
            }
        }

        private HttpContext context;

        public string GetQueryValue(string name)
        {
            if (string.IsNullOrEmpty(Request.QueryString[name]))
                return "";
            else
                return Request.QueryString[name].Trim();
        }

        #endregion

        #region IHttpHandler Members

        public void ProcessRequest(HttpContext context)
        {
            this.context = context;
            this.context.Response.ContentType = "text/plain";

            Operation = this.context.Request["op"];

            switch (Operation)
            {
                case "LoadJobFile":
                    LoadJobFile();
                    break;
                case "ValidateJobField":
                    ValidateJobField();
                    break;
                case "SaveJob":
                    SaveJob();
                    break;
                case "SaveScenario":
                    SaveScenario();
                    break;
                case "GetCheckResult":
                    GetCheckResult();
                    break;
                case "showJobSchedule":
                    ShowJobSchedule();
                    break;
                case "getjobhistory":
                    GetJobHistory();
                    break;
            }
        }

        public bool IsReusable
        {
            get { return true; }
        }

        #endregion

        #region Private Methods

        private void LoadJobFile()
        {
            ValidationResult vResult = new ValidationResult(true);

            try
            {
                HttpPostedFile postedFile = Request.Files["JobFileData"];
                // HttpPostedFile postedFile = Request.Files[0];

                int jobId = 0;
                int.TryParse(Request.Params["jobid"], out jobId);

                JobFileInfo jobFileInfo = StoreManager.Current.JobDefinitionStore.RetrieveJobFileInfo(postedFile);

                Response.StatusCode = 200;

                if (jobFileInfo == null)
                {
                    vResult = new ValidationResult(false, postedFile.FileName + " is not a valid job file");
                }
                else
                {
                    vResult = StoreManager.Current.JobDefinitionStore.ValidateJobDefinition(new JobDefinition()
                    {
                        JobId = jobId,
                        JobName = Guid.NewGuid().ToString(),    // For temporary validation, guid is always unique.
                        FileName = jobFileInfo.FileName,
                        TypeName = jobFileInfo.TypeName,
                        Version = jobFileInfo.Version
                    });

                    if (vResult.Pass)
                    {
                        vResult.Tag = jobFileInfo;
                    }
                }
            }
            catch
            {
                // If any kind of error occurs return a 500 Internal Server error
                Response.StatusCode = 500;
                vResult = new ValidationResult(false, "An error occured");
            }
            finally
            {
                // Response
                string vResultString = JsonConvert.SerializeObject(vResult);
                Response.Write(vResultString);

                // Clean up
                Response.End();
            }
        }

        #region Validate Job Field

        private void ValidateJobField()
        {
            string field = GetQueryValue("fld");

            switch (field)
            {
                case "JobName":
                    ValidateJobName();
                    break;
            }
        }

        private void ValidateJobName()
        {
            ValidationResult vResult = new ValidationResult(true);

            string jobIdStr = GetQueryValue("JobId");
            string jobName = GetQueryValue("JobName");

            int jobId = 0;
            int.TryParse(jobIdStr, out jobId);

            JobDefinition jd = StoreManager.Current.JobDefinitionStore.GetJobDefinitionByJobName(jobName);

            if (jd != null)
            {
                if (jobId != jd.JobId.Value)
                {
                    vResult = new ValidationResult(false, "Job name " + jobName + " already exists.", "DUP_JOBNAME");
                }
            }

            context.Response.Write(JsonConvert.SerializeObject(vResult));
        }

        #endregion

        private void SaveJob()
        {
            string jobDataStr = this.GetQueryValue("JobData");
            string scenariosDataStr = this.GetQueryValue("ScenariosData");
            string tmpFileName = this.GetQueryValue("TempFileName");

            JobDefinition job = JsonConvert.DeserializeObject<JobDefinition>(jobDataStr);
            IList<Scenario> scenarios = JsonConvert.DeserializeObject<List<Scenario>>(scenariosDataStr);

            StoreManager.Current.JobDefinitionStore.SaveJobDefinition(job, tmpFileName, scenarios.ToArray());
        }

        private void SaveScenario()
        {
            Scenario scenario = RetrieveScenarioData();
            string idStr = context.Request.Params["Id"];

            ValidationResult result = StoreManager.Current.JobDefinitionStore.ValidateScenario(scenario);

            if (result.Pass == true)
            {
                if (scenario.Id != null && scenario.Id != 0)
                {
                    Scenario dbScenario = StoreManager.Current.JobDefinitionStore.GetScenario(scenario.Id.Value);

                    dbScenario.ScenarioNO = scenario.ScenarioNO ?? dbScenario.ScenarioNO;
                    dbScenario.ScenarioName = scenario.ScenarioName ?? dbScenario.ScenarioName;
                    dbScenario.URL = scenario.URL ?? dbScenario.URL;
                    dbScenario.Description = scenario.Description ?? dbScenario.Description;

                    StoreManager.Current.JobDefinitionStore.SaveScenario(dbScenario);
                }
            }

            context.Response.Write(JsonConvert.SerializeObject(result));
        }

        private void GetCheckResult()
        {
            int Id = 0;
            bool status = true;
            string message = string.Empty;
            string id = GetQueryValue("jobId");
            if (id != null && int.TryParse(id, out Id))
            {
                var workflows = StoreManager.Current.WorkflowStore.GetWorkflowsContainSpecificJob(Id);

                if (StoreManager.Current.JobStore.GetDeletedJobCount(Id) > 0)
                {
                    status = false;
                    message = CommonString.JobInJobInstance;
                }
                else if (workflows.Count > 0)
                {
                    status = false;
                    List<string> workflowNameList = new List<string>();
                    foreach (var item in workflows)
	                {
                        var workflowData = StoreManager.Current.WorkflowStore.GetWorkflowDataById(item.WorkflowId);

                        if (workflowData != null)
                        {
                            workflowNameList.Add(workflowData.WorkflowName);
                        }
	                }

                    message = string.Format(CommonString.JobInWorkflow, workflowNameList.Join(";\n"));
                }
            }

            var resultToUser = new
            {
                status = status,
                message = message
            };

            string result = JsonConvert.SerializeObject(resultToUser);

            context.Response.Write(result);
        }

        private void ShowJobSchedule()
        {
            List<string> list = new List<string>();
            
            string jobid = GetQueryValue("jobId");
            
            if (!string.IsNullOrWhiteSpace(jobid))
            {
                list = StoreManager.Current.JobStore.GetJobScheduleByID(Convert.ToInt32(jobid));
            }
            string result = JsonConvert.SerializeObject(list);
            context.Response.Write(result);
        }

        private void GetJobHistory()
        {
            int  historyId;
            if(!int.TryParse(GetQueryValue("historyId"),out historyId))
                return;

            JobExecutionHistory history = StoreManager.Current.JobStore.GetJobExecutionHistory(historyId);
            var result = new { history.Id,history.ErrorMessage };
            context.Response.Write(JsonConvert.SerializeObject(result));
        }

        private void TurnDownSchedule(HttpContext context)
        {


        }

        #endregion

        #region Helper Methods

        private Scenario RetrieveScenarioData()
        {
            Scenario scenario = new Scenario();

            string idStr = context.Request.Params["Id"];

            if (!String.IsNullOrEmpty(idStr))
            {
                int id = 0;
                int.TryParse(idStr, out id);

                if (id != 0)
                {
                    scenario.Id = id;
                }
            }

            scenario.ScenarioNO = GetQueryValue("ScenarioNO");
            scenario.ScenarioName = GetQueryValue("ScenarioName");
            scenario.URL = GetQueryValue("URL");
            scenario.Description = GetQueryValue("Description");

            return scenario;
        }

        #endregion
    }

}